﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using MediaRecommender.Model;
using System.IO;

namespace MediaRecommender.Controller
{
    //Media controller that constructs media stores them in the appropriate collection class
    public class MediaController
    {
        private MediaCollection _mediaCollection = MediaCollection.Instance;

        /* For all the createmedia methods instead of returning the media they store the media in the collection class and, 
         * returns true if the media constructed and add or false otherwise
         */
        public bool CreateMedia(List<Author> authors, string title, List<int> genres, string coverUrlIn)
        {
            if (MediaCollection.Instance.GetAllMedia().Select(x => x.Title).Contains(title))
                return false;

            Book newBook = new Book(authors, title, genres, FindMaxMediaId());

            if (MediaCollection.Instance.GetMedia(x => x.Title.Equals(title) && x is Book).Count != 0)
                return false;
            newBook.CoverUrl = coverUrlIn;
            AdaptMediaVector(newBook);

            // For all the createmedia methods the media vector is updated according to the inserted associated person
            foreach (var author in authors)
                newBook.AssociatedPeopleVector[author.ID] = true;

            foreach (bool variable in newBook.AssociatedPeopleVector)
            {
                if (variable)
                    newBook.VectorLength++;
            }

            // Trims the associated person vector to cut away unneeded elemetns
            TrimAssocicatedPersonVector(newBook);

            // Adds the newly created media to the media collection
            MediaCollection.Instance.Add(newBook);

            return true; ;
        }

        public bool CreateMedia(Director director, List<Actor> actors, string title, List<int> genres, string coverUrlIn)
        {
            if (MediaCollection.Instance.GetMedia(x => x.Title.Equals(title) && x is Movie).Count != 0)
                return false;

            Movie newMovie = new Movie(director, actors, title, genres, FindMaxMediaId());
            newMovie.CoverUrl = coverUrlIn;

            AdaptMediaVector(newMovie);

            if (director != null)
                newMovie.AssociatedPeopleVector[director.ID] = true;

            foreach (var actor in actors)
                newMovie.AssociatedPeopleVector[actor.ID] = true;

            foreach (bool variable in newMovie.AssociatedPeopleVector)
            {
                if (variable)
                    newMovie.VectorLength++;
            }

            TrimAssocicatedPersonVector(newMovie);

            _mediaCollection.Add(newMovie);

            return true;
        }

        public bool CreateMedia(GameStudio studio, Publisher publisher, List<int> platforms, string title, List<int> genres, string coverUrlIn)
        {
            if (MediaCollection.Instance.GetMedia(x => x.Title.Equals(title) && x is VideoGame).Count != 0)
                return false;

            VideoGame newGame = new VideoGame(studio, publisher, platforms, title, genres, FindMaxMediaId());
            newGame.CoverUrl = coverUrlIn;

            AdaptMediaVector(newGame);

            if (studio != null)
                newGame.AssociatedPeopleVector[studio.ID] = true;

            if (publisher != null)
                newGame.AssociatedPeopleVector[publisher.ID] = true;

            foreach (bool variable in newGame.AssociatedPeopleVector)
            {
                if (variable)
                    newGame.VectorLength++;
            }

            TrimAssocicatedPersonVector(newGame);

            MediaCollection.Instance.Add(newGame);

            return true;
        }

        private void AdaptMediaVector(Media media)
        {
            if (MediaCollection.Instance.CountPeople() != 0)
                for (int i = 0; i < MediaCollection.Instance.ReturnAllPeople().Count; i++)
                    media.AssociatedPeopleVector.Add(false);

            for (int i = 0; i < Enum.GetNames(typeof(Genre)).Length; i++)
                media.VectorRepresentation.Add(false);

            foreach (var variable in media.Genres)
                media.VectorRepresentation[variable] = true;

            foreach (var variable in media.VectorRepresentation)
            {
                if (variable)
                    media.VectorLength++;
            }
        }

        private int FindMaxMediaId()
        {
            int tempId;
            List<int> maxId = _mediaCollection.GetAllMedia().Select(x => x.ID).ToList();

            if (maxId.Count == 0)
                tempId = -1;
            else
                tempId = maxId.Max();

            tempId++;

            return tempId;
        }

        public void ReadDbFromFile()
        {
            _mediaCollection.ReadDbFromFile();
        }

        public void WriteDbToFile()
        {
            _mediaCollection.WriteDbToFile();
        }

        private void TrimAssocicatedPersonVector(Media media)
        {
            for (int i = media.AssociatedPeopleVector.Count - 1; i >= 0; i--)
            {
                if (!media.AssociatedPeopleVector[i])
                    media.AssociatedPeopleVector.RemoveAt(i);
                else
                    break;
            }
        }
    }
}